
\chapter{Library Tutorial}

In this chapter, we will explore the most useful functions and classes
in the RAP library.
The data files used in the examples can be found in the file, 
{\tt testfiles.tar.gz}, directory in the Downloads section of the RAP web site.
All of the examples assume you have loaded the RAP library using 
\begin{verbatim}
>>> from rap_core import *
\end{verbatim}


\section{RAPLIB}

First we will go over global constants and generic functions.  

\subsection{Constants}
\label{sub:raplib_constants}

There are several atomic physics constants available in RAP.
One of the most useful is {\tt SPECLETTERS} which is an array containing 
spectroscopic letters representing angular momenta.
The following bit of code will convert an integral angular momentum into its
spectroscopic letter:
\begin{verbatim}
>>> li=3
>>> la=SPECLETTERS[li]           # stores `F'
>>> lb=SPECLETTERS[li].lower()   # stores `f'
\end{verbatim}
Note that {\tt SPECLETTERS} stores capital letters, so the {\it lower()}
string function is used to get the lowercase letter in the last line of
the example above.
To do the reverse transformation, use Python's {\it index()} function for lists:
\begin{verbatim}
>>> la='f'
>>> li=SPECLETTERS.index(la.upper())    # stores 3
\end{verbatim}
where we use {\it upper()} to convert the letter into uppercase.
{\tt SPECLETTERS} currently only supports angular momenta up to $L=20$.

The list, {\tt ATOMSYMBOLS}, stores the symbols for all elements from 
hydrogen to ununoctium ($Z=118$).
Since Python arrays start from zero, there is a dummy symbol, `A', in the
zero'th position.  
This symbol can be used to represent a generic atom.
The symbols are capitalized, so use Python's {\it capitalize()} function to 
convert an uppercase or lowercase string to match.
Retrieving the symbol from the nuclear charge and vice versa are similar as
with {\tt SPECLETTERS}:
\begin{verbatim}
>>> z=10
>>> sym=ATOMSYMBOLS[z]                      # stores `Ne'
>>>
>>> sym='FE'
>>> z=ATOMSYMBOLS.index(sym.capitalize())   # stores 26
\end{verbatim}

There are other global arrays, but their values are mainly accessed through
other library functions, so we won't go over them here.
There are several conversion constants, however, which can be useful.
\begin{itemize}
\item {\tt RYDBERG} -- the Rydberg constant, converts energy from Rydbergs (Ry)
to electron-Volts (eV),
\item {\tt INVERSECM} -- converts energy in Ry to wave numbers in 1/cm,
\item {\tt HC\_RYDANG} -- converts energy in Ry to wavelength in Angstroms
(\AA), and
\item {\tt HC\_EVNM} -- converts energy in eV to wavelength in nm.
\end{itemize}
Use these as you would any variable:
\begin{verbatim}
>>> ery=1.0
>>> eev=RYDBERG*ery        # stores 13.6056923
\end{verbatim}


\subsection{Sub-shell functions}

RAP includes several functions to help parse atomic sub-shells.
A sub-shell is a string of the form, $nl$, where $n$ is the integral principal
quantum number and $l$ is the spectroscopic angular momentum.
The standard order of sub-shells starts with `1s' and increments through 
the angular momenta of the current principal quantum number before incrementing
$n$, i.e. `1s', `2s', `2p', `3s', `3p', `3d', etc.
The function, {\tt rlf\_subshell()}, takes an integer, $i$, and returns the 
$i$'th sub-shell string, while {\tt rlf\_ssindex()} performs the reverse 
operation.
Example:
\begin{verbatim}
>>> ss=rlf_subshell(4)        # stores `3s'
>>> i=rlf_ssindex('4f')       # returns 10
\end{verbatim}

The values of $n$ and $l$ can be retrieved from a sub-shell string using
{\tt rlf\_ssdecode()} and vice versa with {\tt rlf\_ssencode()}.
Both of these functions act of sub-shell strings or indices.
Example:
\begin{verbatim}
>>> (n,l)=rlf_ssdecode('3p')          # stores (3,1)
>>> (n,l)=rlf_ssdecode(5)             # stores (3,1)
>>> ss=rlf_ssencode(6,4)              # stores `6g'
>>> i=rlf_ssencode(6,4,index=True)    # stores 20
\end{verbatim}

The maximum occupancy of a sub-shell is returned with {\tt rlf\_ssoccupancy()}:
\begin{verbatim}
>>> w=rlf_ssoccupancy('2p')     # stores 6
>>> w=rlf_ssoccupancy(3)        # stores 6
\end{verbatim}

Finally, there is a function, {\tt rlf\_sssorter}, which assists the intrinsic
Python function, {\it sort()}, to correctly sort a list of sub-shells.
Example:
\begin{verbatim}
>>> sslist=['3d','1s','2p','3s','2s','3p']
>>> sslist.sort(rlf_sssorter)
>>> print sslist
['1s', '2s', '2p', '3s', '3p', '3d']
\end{verbatim}


\subsection{Term string functions}

Term strings, e.g. $^2$P, represent the spin (as $2S+1$) and angular
momentum, $L$, of an $LS$ term.
RAP includes functions to assist in understanding and manipulating these 
strings.
Many of these functions are analogues of sub-shell functions.

To get the values of $2S+1$ and $L$ from a term string and vice versa, use 
{\tt rlf\_termdecode()} and {\tt rlf\_termencode()}:
\begin{verbatim}
>>> (g,l)=rlf_termdecode('2P')      # stores (2,1)
>>> term=rlf_termencode(4,2)        # stores `4D'
\end{verbatim}

We can sort a list of term strings according to, first, spin and then the 
angular momentum:
\begin{verbatim}
>>> terms=['6S','4D','2F','4S']
>>> terms.sort(rlf_termsorter)
>>> print terms
['2F', '4S', '4D', '6S']
\end{verbatim}

The weight of a term is given by $(2S+1)(2L+1)$ which is calculated by
{\tt rlf\_termweight()}.
A list of legal values for the total angular momenta, $2J$, of a term is
returned by {\tt rlf\_term\_2jvals()}.
Examples:
\begin{verbatim}
>>> wgt=rlf_termweight('2P')        # stores 6
>>> j2vals=rlf_term_2jvals('4P')    # stores [1,3,5]
\end{verbatim}

There are also several functions to assist in angular momenta coupling 
calculations.
The function, {\tt rlf\_equiv\_lsterms()}, takes an orbital angular momentum of
a sub-shell and an occupation number and returns a dictionary of possible
terms.  The keys of this dictionary are the terms (tuple with $2S+1$, $L$, and
parity) and the values are the number of duplicates of that term.
When trying to determine the possible terms of a configuration, we must couple
all terms from each partially-filled sub-shell.  
The function, {\tt rlf\_lsterm\_couple()}, performs this task when receiving
two term lists of the format output by {\tt rlf\_equiv\_lsterms()}.
Finally, {\tt rlf\_num\_lsterms()} will count the total number of terms in
the given term list.
For example, say we want the list of allowed terms for the configuration:
2p$^3$ 3p:
\begin{verbatim}
>>> t1=rlf_equiv_lsterms(1,3)                  # term list for p3
>>> print t1
{(4, 0, 1): 1, (2, 2, 1): 1, (2, 1, 1): 1}
>>> t2=rlf_equiv_lsterms(1,1)                  # term list for p1
>>> print t2
{(2, 1, 1): 1}
>>> tt=rlf_lsterm_couple(t1,t2)                # couple t1 and t2
>>> print tt
{(3, 2, 0): 2, (1, 1, 0): 2, (3, 0, 0): 1, (1, 3, 0): 1, (5, 1, 0): 1, 
(1, 0, 0): 1, (3, 3, 0): 1, (1, 2, 0): 2, (3, 1, 0): 3}
>>> print rlf_num_lsterms(tt)
14
\end{verbatim}
This example is not the best way to get the list of allowed terms for a 
configuration.
Instead use the {\tt allowed\_terms()} function in the {\tt rap\_config} 
class.

\subsection{General configuration functions}

Most operations on configuration strings are done through the {\tt rap\_config}
class.
There are two functions, however, which are separate.
The first is the sorting function, {\tt rlf\_confsorter()}, which acts just like
the sorting functions for sub-shells and term strings.
This function only acts of instances of the {\tt rap\_config} class.
Example:
\begin{verbatim}
>>> confs=[]
>>> confs.append(rap_config('1s0 2p'))
>>> confs.append(rap_config('1s0 2s'))
>>> confs.append(rap_config('1s'))
>>> print confs
[1s0 2p1, 1s0 2s1, 1s1]
>>> confs.sort(rlf_confsorter)
>>> print confs
[1s1, 1s0 2s1, 1s0 2p1]
\end{verbatim}

The second function, {\tt rlf\_genconf()}, is an interpreter of strings 
representing multiple configurations by using $n$- and $l$-variables.
It is best understood through the following examples (explanations
follow):
\begin{verbatim}
>>> confs=rlf_genconf('3l')         # an l-variable
>>> print confs
[3s1, 3s0 3p1, 3s0 3d1]
>>> confs=rlf_genconf('nl n=3,4')   # n- and l-variables
>>> print confs
[3s1, 3s0 3p1, 3s0 3d1, 3s0 4s1, 3s0 4p1, 3s0 4d1, 3s0 4f1]
>>> confs=rlf_genconf('nl n=3-5 l=0,1')
>>> print confs
[3s1, 3s0 3p1, 3s0 4s1, 3s0 4p1, 3s0 5s1, 3s0 5p1]
>>> confs=rlf_genconf('2l5')
>>> print confs
[2p3, 2s1 2p4, 2s0 2p5]
>>> confs=rlf_genconf('3s 3l2 l=0,1')
>>> print confs
[3p1, 3s1 3p2]
>>> confs=rlf_genconf('3l 4lp lp=0,1')
>>> print confs
[3s1 4s1, 3s1 4p1, 3s0 3p1 4s1, 3s0 3p1 4p1, 3s0 3d1 4s1, 3s0 3d1 4p1]
\end{verbatim}
In the first example, a single $l$-variable is used; since no range is given,
all possible values are taken.
The second example uses both $n$- and $l$-variables. 
Unlike $l$-variables, all $n$-variables must be given a range.
In this example the range is a comma-delimited list of values, while in the
third example, the range is given by minimum and maximum values separated by
a dash.
Also in the third example, a range is given for the $l$-variable.
The fourth example shows how $l$-variables can be used to allow for promotions
within an $n$-shell.
In the fifth example, we also have promotions within an $n$-shell, but we force
there to be at least one 3s electron.
In the last example, we have two $l$-variables.
The only rules on the $l$-variable names is that they all start with `l' and
only contain letters.
The same rules apply to $n$-variables except that all must start with `n'.

\subsection{{\sc xstar} functions}

{\sc xstar}\footnote{http://heasarc.gsfc.nasa.gov/xstar/xstar.html} represents 
ions using an index defined as
\begin{equation}
 i = \frac{Z(Z+1)}{2}-n_e+1
\end{equation}
where $Z$ is the nuclear charge and $n_e$ is the number of electrons.
This expression is contained in the function, {\tt xstar\_ionencode()}, which
takes in $Z$ and $n_e$ and returns $i$.
The reverse operation is performed by {\tt xstar\_iondecode()}, which takes
the ion index and returns a tuple containing $Z$ and $n_e$.
Examples:
\begin{verbatim}
>>> idx=xstar_ionencode(10,10)      # stores 46
>>> (z,ne)=xstar_iondecode(46)      # stores (10,10)
\end{verbatim}



\section{RAP\_CONFIG}

The {\tt rap\_config} class is a container for configuration strings.  
In many ways, it acts just like a normal string, but there are many functions
to manipulate or query the configuration.
The class can understand input configuration strings in many formats:
\begin{verbatim}
>>> conf=rap_config('2p4')
>>> print conf
2p4
>>> conf=rap_config('1s^2 2s^1 2p^3')
>>> print conf
2s1 2p3
>>> conf=rap_config('1s22s22p63s')
>>> print conf
3s1
>>> conf=rap_config('2p4(3Pe)3p')
>>> print conf
2p4 3p1
>>> conf=rap_config('21522523')       # Eissner notation
>>> print conf
2p2
\end{verbatim}
You can also define a configuration by giving the number of electrons:
\begin{verbatim}
>>> conf=rap_config(5)
>>> print conf
2p1
\end{verbatim}
Often, in lists of configurations, leading empty sub-shells are not written
causing ambiguity for {\tt rap\_config}.  
For example, consider the list of B-like configurations: 2s$^2$ 2p, 2s 2p$^2$,
and 2p$^3$.
To human eyes, there is no problem, but taken by itself, {\tt rap\_config}
reads the last one as a N-like configuration.
To avoid this, you can use the {\it ne} parameter to specify the desired 
number of electrons.
Example:
\begin{verbatim}
>>> conf=rap_config('2p3')
>>> print conf
2p3
>>> conf=rap_config('2p3',ne=5)
>>> print conf
2s0 2p3
\end{verbatim}

The occupancy of a sub-shell can be retrieved using list notation:
\begin{verbatim}
>>> conf=rap_config('2p3',ne=5)
>>> print conf[1],conf[2],conf[3],conf[4]
2 0 3 0
>>> print conf['1s'],conf['2s'],conf['2p'],conf['3s']
2 0 3 0
>>> print conf.occupancy('1s')
2
\end{verbatim}

Some other useful functions which should be self explanatory:
\begin{verbatim}
>>> conf=rap_config('[1s]2p3')
>>> print conf
1s1 2s2 2p3
>>> print conf.num_electrons()
6
>>> print conf.parity()
1
>>> print conf.weight()
40
>>> print conf.valence_subshell()
2p
>>> print conf.allowed_terms()
{'1P': 1, '3S': 1, '3P': 1, '5S': 1, '1D': 1, '3D': 1}
\end{verbatim}

There are also a couple functions which can assist in modifying a configuration
by adding or removing an electron from any sub-shell (default: valence).
In this example, we generate the list of configurations representing K-shell
excitation to the M shell.
\begin{verbatim}
>>> conf=rap_config('2p3')
>>> print conf
2p3
>>> ctmp=conf.pop_electron('1s')
>>> print ctmp
1s1 2s2 2p3
>>> n=3
>>> confs=[ctmp.add_electron(rlf_ssencode(n,l)) for l in range(n)]
>>> print confs
[1s1 2s2 2p3 3s1, 1s1 2s2 2p3 3p1, 1s1 2s2 2p3 3d1]
\end{verbatim}


\section{RAP\_STATES}

Energy level data is stored in a collection of child classes of the 
{\tt rap\_states} parent class.
The child classes cover the coupling schemes used to describe the states
of the ion: configuration-averaged ({\tt rap\_states\_ca}), $LS$ 
({\tt rap\_states\_ls}), and $LSJ$ ({\tt rap\_states\_lsj}).
Currently, the following data file types are supported:
\begin{itemize}
\item {\sc autostructure} olg files ($LS$ and $LSJ$),
\item ADAS adf04 files ($LS$ and $LSJ$),
\item {\sc xstar} type 6 files ($LS$ and $LSJ$),
\item NIST ASCII files ($LSJ$), and
\item CHIANTI data files ($LSJ$).
\end{itemize}
If you want your favorite data type to be supported, contact the author.

Energies are stored in Rydbergs.
Conversions to eV and 1/cm can be made using the RAP constants: RYDBERG and 
INVERSECM.
See Sec.~\ref{sub:raplib_constants}.


\subsection{{\sc autostructure} olg files}
\label{sub:states_olg}

{\sc autostructure}\footnote{http://amdpp.phys.strath.ac.uk/autos/} can
calculate energy level data in $LS$- or $LSJ$-coupling.
There are a couple ways of reading the energy data into RAP.
If you know the coupling scheme that you want, you can initialize the 
appropriate child class directly:
\begin{verbatim}
>>> levs=rap_states_ls('olg.ls')
>>> levs=rap_states_lsj('olg.ic')
\end{verbatim}
There is also a library function which will try to figure out which coupling
scheme is present in the data file; if multiple coupling schemes are present
(such can be the case for olg files), $LSJ$ takes priority over $LS$ which
takes priority over configuration-averaged; this priority can bypassed with 
the {\it cup} argument.
Use the {\it coupling()} function to see which type of data was found.
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ic')   # read in LSJ or LS data
>>> print levs.coupling()
LSJ
>>> print len(levs)                 # print number of levels
125
>>> levs=rlf_loadstates('olg.ic',cup='LS')   # read LS data
>>> print levs.coupling()
LS
>>> print len(levs)
58
\end{verbatim}

The states read into the structure have the same indices as given in the 
data file (if no indices are present, energy ordered indices are used).
The indices do not have to be in energy order and some index values can be
skipped.
The following examples show which indices are present, tests if a single index
is present, and prints the level label and energy using an index:
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ls')
>>> print levs.indices()
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57, 58]
>>> if 6 in levs: print 'YES'
YES
>>> print levs[6]
2s0 2p3 4S
>>> print levs.energy(6)
3.708331
\end{verbatim}

You can also use the intrinsic iterator to loop through all indices:
\begin{verbatim}
>>> aform='%-20s%16.6E'
>>> for i in levs: print aform%(levs[i],levs.energy(i))
2p1 2P                  0.000000E+00
2s1 2p2 4P              1.123184E+00
2s1 2p2 2D              2.123157E+00
2s1 2p2 2S              2.736783E+00
2s1 2p2 2P              2.958824E+00
2s0 2p3 4S              3.708331E+00
2s0 2p3 2D              4.265974E+00
2s0 2p3 2P              4.831386E+00
2p0 3s1 2S              1.095212E+01
2p0 3p1 2P              1.154196E+01
2p0 3d1 2D              1.210174E+01
...                                       # truncated
\end{verbatim}

Specific state information can be accessed using the following functions:
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ic')
>>> ilev=2
>>> print levs[ilev]
2p1 2P_3/2
>>> print levs.parity(ilev)
1
>>> print levs.weight(ilev)
4
>>> print levs.configuration(ilev)
2p1
>>> print levs.term(ilev)
2P
>>> print levs.j2(ilev)
3
>>> print levs.j(ilev)
1.5
>>> print levs.seniority(ilev)
1
\end{verbatim}
For some configurations, there can be multiple states with the same term
label.
RAP assigns a seniority number to keep these terms distinct which starts 
from one and increases in energy order .  
It must be noted that this seniority number does not have the usual definition
of seniority used in atomic physics.
The standard definition does not always produce a unique set of term labels
for complex configurations, so we have replaced it with a label guaranteed to
give unique labels.
Also note that the functions retrieving the total angular momentum ($J$) are
not available for $LS$ data.

A set of filter functions exists to select a subset of level indices based
on a variety of criteria.
These are:
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ic')
>>> print levs.cfilter('2s1 2p2')      # by configuration
[3, 4, 5, 6, 7, 8, 9, 10]
>>> print levs.tfilter('4S')           # by term string
[11, 32, 86]
>>> print levs.j2filter(9)             # by 2J
[42, 92, 114]
>>> print levs.jfilter(4.5)            # by J
[42, 92, 114]
>>> print levs.symfilter(9,0)          # 2J and parity
[92, 114]
\end{verbatim}
The {\it symfilter()} function takes arguments of $2S+1$, $L$, and parity for
$LS$ data.
Also, all of the above functions take the optional argument, {\it subset}, 
which is a list of indices to act on.
This allows you to combine filters; e.g.
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ic')
>>> ilevs=levs.cfilter('2s1 2p2')
>>> ilevs=levs.j2filter(3,subset=ilevs)
>>> print ilevs
[4, 6, 10]
>>> for i in ilevs: print levs[i]
2s1 2p2 4P_3/2
2s1 2p2 2D_3/2
2s1 2p2 2P_3/2
\end{verbatim}

The {\tt rap\_states} classes allow for mapping between data sets in order to 
compare energies.
In the following example, we will load in both LS and LSJ {\sc autostructure}
data and then term-average the $LSJ$ data.
The resulting $LS$-averaged data set will have terms in a different energy order
than the pure $LS$ dataset.
We will then map the indices from the averaged data set to use the indices from
the $LS$ data set so that a single set of indices can be used to refer to a
common set of states.
\begin{verbatim}
>>> levs1=rlf_loadstates('olg.ic')
>>> levs2=rlf_loadstates('olg.ls')
>>> levs1p=levs1.LS_average()
>>> print levs2.label(35)
2s1 2p1 3d1 2P#2
>>> print levs1p.label(35)
2s0 2p2 3p1 2S
>>> levs1p.set_lmap(levs2)
>>> print levs1p.label(35,imap=True)
2s1 2p1 3d1 2P#2
\end{verbatim}
All relevant functions accept the optional {\it imap} argument which will route
the given index though the state map.


\subsection{{\sc xstar} type 6 files}

Like {autostructure} olg files, 
{\sc xstar}\footnote{http://heasarc.gsfc.nasa.gov/xstar/xstar.html} type 6
files can contain energy level data in multiple coupling schemes.
Therefore, it is recommened that you use {\it rlf\_loadstates()} to read in
a type 6 file and {\it coupling()} to see what kind of data was found. 
For cases where a file may simultaneously have data from different coupling
schemes, you can use the {\it cup} parameter to select which data you want to
grab.
A warning: there are cases where a configuration only contains states whose
coupling scheme is ambiguous, e.g. 1s$^2$.
If all other unambiguous states in the file have the same coupling scheme, RAP
will assume these ambiguous configurations to have the same.
However, when multiple coupling schemes are present, the ambiguous states will
be included regardless of the {\it cup} parameter.
This can lead to having duplicate states if you have a script combining data 
from all coupling schemes.
The state indices can be used to identify such duplicate states.
If RAP finds multiple coupling schemes for states within the same configuration,
it will return an error.

In this example, we will read in two type 6 files and identify the coupling
scheme of the data found.
\begin{verbatim}
>>> levs=rlf_loadstates('d343t006')
>>> print levs.coupling()
LSJ
>>> levs=rlf_loadstates('d350t006')
>>> print levs.coupling()
LS
\end{verbatim}

See Sec.~\ref{sub:states_olg} on {\sc autostructure} olg files for available 
operations for these instances.


\subsection{ADAS adf04 files}

ADAS\footnote{http://www.adas.ac.uk/} adf04 files contain energy data which can
belong to multiple coupling schemes.
Loading this data is similar to {\sc xstar} type 6 files:
\begin{verbatim}
>>> levs=rlf_loadstates('adf04.ic')
>>> print levs.coupling()
LSJ
>>> levs=rlf_loadstates('adf04.ls')
>>> print levs.coupling()
LS
\end{verbatim}

Note that some adf04 files have energies which are bundled over $n$-shells.
RAP does not currently support such data and {\it rlf\_loadstates()} will 
return an error.


\subsection{NIST ASCII files}
\label{sub:states_nist}

RAP supports the ASCII format given on the NIST ASD web 
page\footnote{http://www.nist.gov/pml/data/asd.cfm}.
You must be sure to retrieve the energies in Ry, however.
Only $LSJ$ data is stored in NIST so you can initialize a {\tt rap\_states\_lsj}
instance directly or use the {\it rlf\_loadstates()} function as before.
\begin{verbatim}
>>> levs=rap_states_lsj('fe18.en.nist')
rap_core.py:2912: UserWarning: 17 levels not understood and skipped
  warnings.warn(msg)
>>> print len(levs)
53
\end{verbatim}
Note the warning returned when trying to read the energy data.
For some systems, $LSJ$-coupling is not a good description of the state and
NIST provides an alternate description. 
These states are not understood by {\tt rap\_states\_lsj} and skipped; all 
other levele are loaded.
In the future, a class will be created to store data using just $J$ and the
parity.  
This class will be able to read all level data in the NIST ASCII file.
The creation of this class will be expedited by requests.


\subsection{CHIANTI elvlc files}

Energy level files from CHIANTI\footnote{http://www.chianti.rl.ac.uk/} store
both observed and theoretical values.
Either of these can be read into RAP.
By default, experimental energies are taken when available and theoretical
values are used for all other levels.
An optional argument {\it priority} can be used to select which energy to
favor: `experimental' or `theoretical' (only the first letter of each is
needed).
There is also an optional flag, {\it only}, that, when set to True means that
only the energies belonging to the selected priority will be loaded. 
All other energies will be skipped.
Examples:
\begin{verbatim}
>>> levs1=rlf_loadstates('fe_18.elvlc')
>>> levs2=rlf_loadstates('fe_18.elvlc',priority='th')
>>> print len(levs1),len(levs2)
337 337
>>> print levs1.energy(2),levs2.energy(2)
0.934768761397 0.95529961098
>>> levs3=rlf_loadstates('fe_18.elvlc',only=True)   # only experimental
>>> print len(levs3)
61
\end{verbatim}


\section{RAP\_MIX}

This class stores mixing data between states.
All level data is provided from a {\tt rap\_states} class, so any coupling
scheme, in theory, is supported.
However, currently, only {\sc autostructure} olg files are supported, so 
{\tt rap\_mix} is limited to $LS$ and $LSJ$ at this time.
To read mixing data from an olg file, do the following:
\begin{verbatim}
>>> mix=rap_mix('olg.ic')
>>> print mix.num_levels()
125
>>> mix=rap_mix('olg.ic',cup='LS')
>>> print mix.num_levels()
58
\end{verbatim}
As you can see in the example, the {\it cup} parameter allows you to read in
the $LS$ data in the $LSJ$ olg file.

Mixing between states is only allowed within a symmetry, therefore it is 
around symmetries that mixing coefficients are stored and retrieved.
To get the list of symmetries and to retrieve the symmetry of a level, do:
\begin{verbatim}
>>> mix=rap_mix('olg.ic',cup='LS')
>>> print mix.symmetries()
[(2, 0, 0), (2, 0, 1), (2, 1, 0), (2, 1, 1), (2, 2, 0), (2, 2, 1), 
(2, 3, 0), (2, 3, 1), (2, 4, 0), (4, 0, 0), (4, 0, 1), (4, 1, 0), 
(4, 1, 1), (4, 2, 0), (4, 2, 1), (4, 3, 0), (4, 3, 1)]
>>> print mix.symmetry(1)
(2, 1, 1)
\end{verbatim}

Mixing coefficients can be retrieved with the {\it coeff()} function.
This function will return a dictionary where the keys are the level indices
and the values are the mixing coefficients.
To get the mixing percentage, you need to square the coefficient.
For example, here we print the mixing coefficients and percentages for the 
ground state in our sample file:
\begin{verbatim}
>>> mix=rap_mix('olg.ic',cup='LS')
>>> coeff=mix.coeff(1)
>>> aform='%5i%12.3f%12.3f'     # format statement
>>> for (i,c) in coeff.iteritems(): print aform%(i,c,c**2)
    1       0.982       0.964
   35      -0.028       0.001
    8      -0.186       0.034
   41       0.000       0.000
   10      -0.005       0.000
   13       0.017       0.000
   49      -0.001       0.000
   24      -0.004       0.000
   57       0.003       0.000
   26       0.022       0.000
\end{verbatim}


\section{RAP\_RAD}

Einstein A coefficients, or A-values, are stored in {\tt rap\_rad}.
This class is a child class of {\tt rap\_trans} which contains common
structures and functions for all transition data.
Therefore, many of the functions demonstrated here are actually defined
in that class.
In addition, {\it rap\_rad} also calculates the lifetimes of all upper states
as the data is being read in.

As with {\tt rap\_mix}, level information is provided via a {\tt rap\_states}
instance which must be compatible with the file containing the radiative data.
For some data types, e.g. {\sc autostructure} olg files, energies and
radiative data are in the same file, so only this file needs to be provided
when initializing a {\tt rap\_rad} instance.
Other formats, such as {\sc xstar}, have energies and A-values in separate
files.
In this case, the {\tt rap\_states} instance must be created first and passed
to {\tt rap\_rad} along with the name of the file with the radiative data.
All coupling schemes are supported.

\subsection{{\sc autostructure} olg files}

As mentioned above, radiative data and level definitions exist in the same
olg file.
So, loaded radiative data is an easy thing:
\begin{verbatim}
>>> rad=rap_rad('olg.ic')
>>> print len(rad)
7670
>>> print rad.num_levels()
125
>>> if (1,2) in rad: print 'YES'
YES
>>> print rad[(1,2)]
0.379901117
>>> print rad.wavelength(1,2)
28699.1818249
\end{verbatim}
Python's intrinsic {\it len()} function has been tasked to return the total
number of transitions found.
You can return the number of levels with {\it num\_levels()}.
The class also supports list notation for retrieving A-values.
Note that the level indices must be passed as a tuple, e.g. (1,2), with the
convention that the lower-energy index is first.
Finally, the energies in the {\it rap\_states} object can be accessed to 
give the transition wavelength.

If you do not want to store all the A-values in the file, you can specify
limits on the initial and final state indices.
In the following example, we will only read enough transitions to guarantee
that we have all transition data between the first two configurations.
Unlike the last example, we will read in the energy data first in order to 
determine the indices we want.  
Then we will pass this object into the {\tt rap\_rad} class when reading the
A-values along with the limits on the indices.
\begin{verbatim}
>>> levs=rlf_loadstates('olg.ic')
>>> confs=levs.configurations()
>>> ilevs=levs.cfilter(confs[0])
>>> flevs=levs.cfilter(confs[1])
>>> print ilevs
[1, 2]
>>> print flevs
[3, 4, 5, 6, 7, 8, 9, 10]
>>> rad=rap_rad('olg.ic',levs=levs,iminlev=min(ilevs),\
    imaxlev=max(ilevs),fminlev=min(flevs),fmaxlev=max(flevs))
>>> print len(rad)
16
>>> print rad.transitions()
[(1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10),
(2, 3),(2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (2, 10)]
\end{verbatim}
All of the limit arguments (e.g. {\it iminlev}) are optional.
If you want, for example, to load A-values from only the ground state, you just
need to specify {\it imaxlev}=1; the rest you can leave out.
At the end of this example, we show the {\it transitions()} function which 
returns the list of all transition tuples.
A useful function for iterating through all the data, but it is not recommended
to print this to screen when you have a lot of transitions.

You can also change the limits after reading the data file.
Note that this will delete data from the structure, so limits cannot be 
increased.
\begin{verbatim}
>>> rad=rap_rad('olg.ic')
>>> print len(rad)
7670
>>> rad.set_initial_limit(maxlev=1)
>>> print len(rad)
123
\end{verbatim}

Thus far, all function shown here are general to the {\it rap\_trans} parent
class.
There are, however, a couple functions specific to {\it rap\_rad}, including:
\begin{verbatim}
>>> print rad.avalue((1,2))       # alternate to rad[(1,2)]
0.379901117
>>> print rad.avalue(1,2)         # tuple notation not required!
0.379901117
>>> print rad.gfvalue(1,2)        # gf-value
1.87642353524e-07
>>> print rad.gavalue(1,2)        # ga-value
1.519604468
>>> print rad.lifetime(2)         # lifetime in seconds
2.63226391093
\end{verbatim}


\subsection{{\sc xstar} type 50 files}

Radiative data in {\sc xstar} is stored separately from level energies.
Therefore, you must first read in the type 6 file before reading in the 
A-values.
\begin{verbatim}
>>> levs=rlf_loadstates('d343t006')
>>> print len(levs)
337
>>> rad=rap_rad('d343t050',levs=levs)
>>> print len(rad)
8594
\end{verbatim}

There is also a routine to write {\sc xstar} type 50 files. 
Any data loaded into {\tt rap\_rad} can be written, but you must make sure
that the ionization potential is set in the {\tt rap\_states} object.
In this example, we will read in the A-values from an {\sc autostructure} olg
file, set the ionization potential (in Ry), and then write the {\sc xstar} 
type 50 file:
\begin{verbatim}
>>> rad=rap_rad('olg.ic',imaxlev=1)          # just from ground
>>> print rad.levs().ionization_threshold()  # check for IP
None
>>> rad.levs().set_ionization_threshold(19.548)   # from NIST
>>> rad.write_xstar('tmp.dat')
\end{verbatim}


\subsection{ADAS adf04 files}

Just like {\sc autostructure}, ADAS stores level energies and radiative data
in the same file.
So, reading in this data is straightforward:
\begin{verbatim}
>>> rad=rap_rad('adf04.ic')
>>> print len(rad)
17765
\end{verbatim}


\subsection{NIST ASCII files}

You can download the lines table from NIST in ASCII format and read it into
{\tt rap\_rad}, but you must also have the ASCII version of the levels table
for the same ion.
Just as with {\sc xstar} files, you need to make a {\tt rap\_states} instance
prior to reading the transition data.
\begin{verbatim}
>>> levs=rlf_loadstates('fe18.en.nist')
rap_core.py:3022: UserWarning: 17 levels not understood and skipped
  warnings.warn(msg)
>>> rad=rap_rad('fe18.rad.nist',levs=levs)
>>> print len(rad)
18
\end{verbatim}
The warning message was discussed in Sec.~\ref{sub:states_nist} and can
be ignored.


\subsection{CHIANTI wgfa files}

To read in CHIANTI A-values, we follow the same procedure as with {\sc xstar}
files.
The levels file is read in first and passed to {\tt rap\_rad} with the filename
of the radiative data file.
In this example, just transitions involving the ground states are read in.
\begin{verbatim}
>>> levs=rlf_loadstates('fe_18.elvlc')
>>> rad=rap_rad('fe_18.wgfa',levs=levs,imaxlev=1)
>>> print len(rad)
311
\end{verbatim}






